#ifndef _OS_MEM_H_
#define _OS_MEM_H_

#include "types.h"

#define MEM_MAGIC_NUM			0x55555555
#define MEM_REGION_MAGIC_NUM		0x5555

#define MEM_STATUS_FREE			0
#define MEM_STATUS_OCCUPIED		1

#define MAGIC_FIELD_LEN 1

#define OS_MEM_CHECKING
#ifdef OS_MEM_CHECKING
	#define SET_MAGIC_NUM(f)	f = MEM_MAGIC_NUM
	#define CHECK_MAGIC_NUM(f)	(f == MEM_MAGIC_NUM)
//	#define MEM_DEBUG_PRINT printf
	#define MEM_DEBUG_PRINT(...)
#else
	#define SET_MAGIC_NUM(f)	
	#define CHECK_MAGIC_NUM(f)	(1)
	#define MEM_DEBUG_PRINT(...)
#endif

typedef struct
{
	uint32_t magic_num[MAGIC_FIELD_LEN];
	uint32_t region_len;
	uint16_t buffer_header_len;
	uint16_t pad;
}mem_region_t;


typedef struct
{
	uint32_t magic_start[MAGIC_FIELD_LEN];
	uint32_t buffer_len;
	uint8_t buffer_status;
	uint8_t pad;	
	uint16_t pad2;
}mem_buffer_t;

typedef struct mem_block_t
{
	uint32_t magic_start[MAGIC_FIELD_LEN];
	uint32_t block_index;
	struct mem_block_t *next_free;
}mem_block_t;



bool mem_region_init(uint8_t *start_ptr, uint32_t len, uint16_t header_len);
bool alloc_mem_buffer(uint8_t *start_ptr, uint32_t len, mem_buffer_t **buf_ptr);
bool free_mem_buffer(mem_buffer_t *buf_ptr);

bool mem_blocks_init(uint8_t *start_ptr, uint32_t block_len, uint32_t num_blocks);
bool free_mem_block(uint8_t **freelist_p, mem_block_t *block_ptr);
mem_block_t * alloc_mem_block(uint8_t **freelist_p);

void user_mem_init(void);


// User functions
uint8_t *malloc(uint32_t size);
uint8_t *calloc(uint32_t num, uint32_t blk_size);
void free(void *ptr);

void memset(uint8_t *ptr, uint8_t value, uint32_t size);
void memcpy(uint8_t *dst, uint8_t *src, uint32_t size);

#endif
